package com.time.workbench.efficient.service;

import cn.hutool.core.lang.ObjectId;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.time.workbench.core.exception.BizException;
import com.time.workbench.core.util.AuthUtil;
import com.time.workbench.efficient.entity.bo.Application;
import com.time.workbench.efficient.entity.bo.ApplicationServer;
import com.time.workbench.efficient.entity.bo.DeployRecord;
import com.time.workbench.efficient.entity.bo.Server;
import com.time.workbench.efficient.handle.AbstractDeploy;
import com.time.workbench.efficient.handle.SpringBootDeploy;
import com.time.workbench.efficient.mapper.DeployRecordMapper;
import com.time.workbench.efficient.util.IpUtil;
import com.time.workbench.system.entity.vo.SystemDictVO;
import com.time.workbench.system.service.SystemDictService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;


/**
 * 部署service
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class DeployRecordService extends ServiceImpl<DeployRecordMapper, DeployRecord> implements IService<DeployRecord> {
    /**
     * 应用
     */
    private final ApplicationService applicationService;

    /**
     * 服务器
     */
    private final ServerService serverService;

    /**
     * 应用服务器关联
     */
    private final ApplicationServerService applicationServerService;

    /**
     * 字典
     */
    private final SystemDictService systemDictService;

    private final RedisTemplate<String, String> redisTemplate;




    public List<String> deploy(Integer applicationId, Integer environmentId) {
        Application application = applicationService.getById(applicationId);
        List<ApplicationServer> applicationServer = applicationServerService.getApplicationServer(applicationId, environmentId);
        Map<String, String> applicationTypes = systemDictService.getMapByTypeCode("applicationType");
        List<String> deployTaskId = applicationServer.stream().map(item -> {
            Server server = serverService.getById(item.getServerId());
            log.info("部署应用code:{} 名称:{}", application.getCode(), application.getName());
            log.info("部署应用类型:{}", applicationTypes.get(application.getApplicationType()));

            String deployCode = IdUtil.objectId();
            MDC.put("deployCode", deployCode);

            switch (application.getApplicationType()) {
                case 1:
                    //FIXME 单独部署取消, 发布单发布
                  /*  SpringBootDeploy springBootDeploy = new SpringBootDeploy();
                    springBootDeploy.setDeployTaskId(deployCode);
                    // 内网是否可以连接
                    boolean privateIsConnection = !StrUtil.isEmpty(server.getPrivateIp()) && IpUtil.isHostReachable(server.getPrivateIp(), 3000);

                    springBootDeploy.setIp(privateIsConnection ? server.getPrivateIp() : server.getPublicIp());
                    springBootDeploy.setPort(server.getPort());
                    springBootDeploy.setUserName(server.getUsername());
                    springBootDeploy.setPassword(server.getPassword());
                    springBootDeploy.setGitRemoteAddress(application.getGitAddress());
                    springBootDeploy.setGitPullBaseDirectory(server.getSourcePath());
                    springBootDeploy.setBranch(item.getDeployBranch());
                    springBootDeploy.setProjectCode(application.getCode());
                    springBootDeploy.setDeployPath(server.getDeployPath());
                    springBootDeploy.setStartUpSuccessConsumer(deployCodeItem -> {
                        updateStatus(deployCodeItem, 2);
                    });
                    springBootDeploy.setStartUpFailConsumer(deployCodeItem -> {
                        updateStatus(deployCodeItem, 3);
                    });
                    CompletableFuture<Void> future = CompletableFuture.runAsync(springBootDeploy::startUp);*/

                    break;
                default:
                    throw new BizException("暂不支持的服务类型: " + applicationTypes.get(application.getApplicationType()));
            }

            // 存库
            DeployRecord deployRecord = new DeployRecord();
            deployRecord.setCode(deployCode);
            deployRecord.setApplicationId(applicationId);
            deployRecord.setEnvironmentId(environmentId);
            deployRecord.setServerId(server.getId());
            deployRecord.setDeployUserId(AuthUtil.getCurrUserId());
            // 部署中
            deployRecord.setDeployStatus(1);
            save(deployRecord);
            return deployCode;
        }).collect(Collectors.toList());

        return deployTaskId;
    }


    private void updateStatus(String deployCode, Integer status) {
        lambdaUpdate().eq(DeployRecord::getCode, deployCode).set(DeployRecord::getDeployStatus, status).update();
    }


    public DeployRecord getDeployByCode(String deployCode) {
        return lambdaQuery().eq(DeployRecord::getCode, deployCode).one();
    }


    public List<String> getLogByCode(String deployCode) {
        return baseMapper.selectLog(deployCode);
    }


}
